package medOffice.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import medOffice.Consulta;
import medOffice.Enuns.EstadoDaConsulta;
import medOffice.Enuns.TipoDeConsulta;
import medOffice.Enuns.Urgencia;

/**
 * Classe que inicializa o BD da Consulta.
 * @author Tiago Leite - tiagohsl@lcc.ufcg.edu.br
 * @version 1.0 </br> 30/11/09
 *
 */

public class ConsultaDAO {
	
	protected Connection conexao;
	
		
	/**
	 * Construtor da classe
	 * 
	 * @param Connection conexao
	 */
	public ConsultaDAO(Connection conexao){
		this.conexao = conexao;
		procedimento();
	}
	
	/**
	 * Construtor default da classe
	 */
	public ConsultaDAO(){
		this.conexao = ConnectionFactory.getConnection();
		procedimento();
	}
	
	/**
	 * Metodo que cria a tabela caso ela nao exista
	 * e realiza a connexao com o BD.
	 */
	private void procedimento(){
		PreparedStatement stmt;
		
		String sql = "create table if not exists Consulta(estadoConsulta ENUM('EM_ESPERA','ATENDIDO','NAO_ATENDIDO')" +
			"not null, tipoConsulta ENUM('CONSULTA', 'RETORNO') not null, urgencia ENUM('S', 'N') not null," +
			"cpfPaciente varchar(25) , data date, hora time, foreign key(cpfPaciente) references Paciente(cpf))";

		
		try {
			stmt = conexao.prepareStatement(sql);
			stmt.execute();
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}
	
	/**
	 * Metodo que cria um objeto Consulta no BD de Consulta. 
	 * @param Paciente paciente
	 * @throws SQLException
	 */
	public void create(Consulta consulta) throws SQLException {
		String sql = "insert into Consulta(estadoConsulta, tipoConsulta," +
				" urgencia, cpfPaciente, data, hora) values (?,?,?,?,?,?)";

		PreparedStatement stmt = conexao.prepareStatement(sql);		
		
		if (consulta.getEstadoDaConsulta() != null) {
			stmt.setString(1, consulta.getEstadoDaConsulta().toString());
		}

		if (consulta.getTipoDeConsulta() != null) {
			stmt.setString(2, consulta.getTipoDeConsulta().toString());
		}
		
		if (consulta.getUrgencia() != null) {
			stmt.setString(3, consulta.getUrgencia().toString());
		}
		
		if (consulta.getPaciente() != null) {
			stmt.setString(4, consulta.getPaciente().getCPF());
		}		
		
		if (consulta.getData() != null) {
			java.util.Date dataUtil = consulta.getData().getTime();
			java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());			
			stmt.setDate(5, dataSql);
		}
		
		if (consulta.getHoraConsulta() != null) {
			stmt.setTime(6, consulta.getHoraConsulta());
		} 
		
		
		stmt.execute();
		stmt.close();
	}
	
	/**
	 * Metodo que fecha uma conexao com o banco de dados.
	 * @throws Exception
	 */
	public void closeConnection() throws Exception{
		conexao.close();
	}
	
	
	/**
	 * Metodo que recupera e imprime todos os dados de todos os pacientes do BD
	 * da clinica.
	 * @throws SQLException
	 * @throws ParseException 
	 */
	public void recuperaDadosConsultas() throws SQLException, ParseException {
		PreparedStatement stmt = conexao.prepareStatement("select * from Consulta," +
				" Paciente where Consulta.cpfPaciente = Paciente.cpf ORDER BY Consulta.data");
				

		ResultSet rs = stmt.executeQuery();		

		List<Consulta> aImprimir= convertePesquisaEmLista(rs);
		
		for(Consulta cons: aImprimir){
			System.out.println("Nome do Paciente: " + cons.getPaciente().getNome() + " | Telefone: " +
					cons.getPaciente().getTelefone() + " |  Data da consulta: " +  
					new SimpleDateFormat("dd/MM/yyyy '|Hora da consulta:' HH:mm").format(cons.getData().getTime()) +
					" | Urgencia: " + cons.getUrgencia().toString());
		}
		System.out.println(aImprimir.size());
		
		rs.close();
		stmt.close();
	}
	
	/**
	 * Metodo que atualiza o cpf de uma paciente.
	 * @param String cpf
	 * @param String novoCpf
	 * @throws SQLException
	 */
	public void update(String cpf, String novoCpf) throws SQLException {
		
		String sql = "update Consulta set cpfPaciente=(?) where cpfPaciente=(?)";
		PreparedStatement stmt = conexao.prepareStatement(sql);

		stmt.setString(1, novoCpf);
		stmt.setString(2, cpf);
		
		stmt.execute();
		stmt.close();
		
	}
	
	/**
	 * Metodo que atualiza os dados de uma consulta.
	 * Obs.: (nao muda data e hora)
	 * @param Consulta consulta
	 * @throws SQLException
	 */
	public void editaConsulta(Consulta consulta) throws SQLException {		
		String sql = "update Consulta set estadoConsulta=?, tipoConsulta=?, urgencia=?," +
				"cpfPaciente=? where data=? and hora=?";
		
		PreparedStatement stmt = conexao.prepareStatement(sql);
		stmt.setString(1, consulta.getEstadoDaConsulta().name());
		stmt.setString(2, consulta.getTipoDeConsulta().name());
		stmt.setString(3, consulta.getUrgencia().name());
		stmt.setString(4, consulta.getPaciente().getCPF());
		stmt.setTime(6, consulta.getHoraConsulta());
		
		java.util.Date dataUtil = consulta.getData().getTime();
		java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());
		stmt.setDate(5, dataSql);	
		
		stmt.executeUpdate();		
		stmt.close();
	}		
	
	
	/**
	 * Metodo que deleta uma consulta passando como parametro
	 * o cpf de um dado paciente.
	 * @param String cpf
	 * @throws SQLException
	 */
	public void delete(String cpf) throws SQLException {
		String sql = "delete from Consulta where cpfPaciente=(?)";
		PreparedStatement stmt = conexao.prepareStatement(sql);

		stmt.setString(1, cpf);		
				
		stmt.execute();
		stmt.close();		
	}		
	
	/**
	 * Metodo usado para deletar uma consulta especifica do banco de dados
	 * @param Consulta consulta
	 * @throws SQLException
	 */
	public void delete(Consulta consulta) throws SQLException {
		String sql = "delete from Consulta where data = (?) and hora = (?)";
		PreparedStatement stmt = conexao.prepareStatement(sql);
		
		java.util.Date dataUtil = consulta.getData().getTime();
		java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());
		stmt.setDate(1, dataSql);
		
		stmt.setTime(2, consulta.getHoraConsulta());
		
		stmt.execute();
		stmt.close();
	}
	
	/**
	 * Metodo que recebe uma data qualquer e deleta todas as consultas daquele dia.
	 * @param String data desejada no formato dd/mm/aaaa
	 * @throws SQLException
	 * @throws ParseException
	 */
	public void deleteConsultasDoDia(String data) throws SQLException, ParseException {
		String sql = "delete from Consulta where data=(?)";
		
		PreparedStatement stmt = conexao.prepareStatement(sql);
		Calendar dataCalendar = PacienteDAO.conversorData2(data);
		
		java.util.Date dataUtil = dataCalendar.getTime();
		java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());
		
		stmt.setDate(1, dataSql);
		
		stmt.execute();
		stmt.close();
	}
	
	/**
	 * Metodo que recebe um Calendar com uma data qualquer 
	 * e deleta todas as consultas daquele dia.
	 * @param Calendar dia
	 * @throws SQLException
	 * @throws ParseException
	 */
	public void deleteConsultasDoDia(Calendar dia) throws SQLException, ParseException {
		String sql = "delete from Consulta where data=(?)";
		
		PreparedStatement stmt = conexao.prepareStatement(sql);
		
		
		java.util.Date dataUtil = dia.getTime();
		java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());
		
		stmt.setDate(1, dataSql);
		
		stmt.execute();
		stmt.close();
	}

	/**
	 * Metodo acessador que resgata uma lista de consultas ordenadas por data.
	 * @return List<Consulta> consultas.
	 * @throws SQLException 
	 */
	public List<Consulta> getListaConsultas() throws SQLException {
		
				
		PreparedStatement stmt = conexao.prepareStatement("select * from Consulta," +
		" Paciente where Consulta.cpfPaciente = Paciente.cpf ORDER BY Consulta.data");
		
		ResultSet rs = stmt.executeQuery();
		
		return convertePesquisaEmLista(rs);
	}
	
	/**
	 * Metodo que recebe uma pequisa em banco de dados
	 * e retorna uma lista das consultas
	 * @param ResultSet rs
	 * @return List<Consulta>
	 * @throws SQLException
	 */
	public List<Consulta> convertePesquisaEmLista(ResultSet rs) throws SQLException{
		List<Consulta> listaConsultas = new ArrayList<Consulta>();
		
		while (rs.next()) {
			try {
				Calendar datanCon = PacienteDAO.conversorData(rs.getString("data").toString());
				Calendar atual = new GregorianCalendar();
				atual.setTimeInMillis(rs.getTime("hora").getTime());
				datanCon.set(Calendar.HOUR_OF_DAY, atual.get(Calendar.HOUR_OF_DAY));
				datanCon.set(Calendar.MINUTE, atual.get(Calendar.MINUTE));
												
				Consulta consultaTemp = new Consulta(datanCon);
				consultaTemp.setEstadoDaConsulta(EstadoDaConsulta.valueOf(rs.getString("estadoConsulta")));
				consultaTemp.setTipoDeConsulta(TipoDeConsulta.valueOf(rs.getString("tipoConsulta")));
				consultaTemp.setUrgencia(Urgencia.valueOf(rs.getString("urgencia")));
				consultaTemp.setPaciente(PacienteDAO.recuperaObjetoPaciente(rs.getString("cpfPaciente"), conexao));
				
				
				
				if (!listaConsultas.contains(consultaTemp)) {
					listaConsultas.add(consultaTemp);				
				}
				
			} catch (Exception e) {				
				e.printStackTrace();
			}
			
			
			
		}
		rs.close();
		return listaConsultas;
	}
	
	/**
	 * Metodo que resgata uma lista com todas as consultas de acordo
	 * com a urgencia desejada. (S ou N) 
	 * @param Urgencia urgencia
	 * @return List<Consulta> Lista das consultas.
	 * @throws SQLException
	 */
	public List<Consulta> listaConsultasPorUrgencia(Urgencia urgencia) throws SQLException {
		PreparedStatement stmt = conexao.prepareStatement("select * from Consulta," +
				" Paciente where Consulta.cpfPaciente = Paciente.cpf and " +
				"Consulta.urgencia = (?) ORDER BY Consulta.data");
		
		stmt.setString(1, urgencia.getNome());
		ResultSet rs = stmt.executeQuery();
		
		
		return convertePesquisaEmLista(rs);
			
	}
	
	/**
	 * Metodo que resgata uma lista de todas as consultas de uma determinada data.
	 * @param Calendar data 
	 * @return List<Consulta> Lista das consultas.
	 * @throws SQLException 
	 */
	public List<Consulta> listaConsultasPorDataDia(Calendar dataDia) throws SQLException {
		PreparedStatement stmt = conexao.prepareStatement("select * from Consulta," +
		" Paciente where Consulta.cpfPaciente = Paciente.cpf and Consulta.data = (?) ORDER BY Consulta.data");
		java.util.Date dataUtil = dataDia.getTime();
		java.sql.Date dataSql = new java.sql.Date(dataUtil.getTime());
		
		stmt.setDate(1, dataSql);
		
		ResultSet rs = stmt.executeQuery();
		
		return convertePesquisaEmLista(rs);
	}

}
